package edu.pku.sei.transformation.atl.codegen;

import edu.pku.sei.transformation.atl.rule.*;

public class ATLGenerator
{
  protected static String nl;
  public static synchronized ATLGenerator create(String lineSeparator)
  {
    nl = lineSeparator;
    ATLGenerator result = new ATLGenerator();
    nl = null;
    return result;
  }

  public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
  protected final String TEXT_1 = "-- @path ";
  protected final String TEXT_2 = ":";
  protected final String TEXT_3 = NL;
  protected final String TEXT_4 = NL + "module ";
  protected final String TEXT_5 = ";";
  protected final String TEXT_6 = NL + "refine ";
  protected final String TEXT_7 = NL + "create ";
  protected final String TEXT_8 = ", ";
  protected final String TEXT_9 = ":";
  protected final String TEXT_10 = " from ";
  protected final String TEXT_11 = ", ";
  protected final String TEXT_12 = ":";
  protected final String TEXT_13 = ";";
  protected final String TEXT_14 = NL + "uses ";
  protected final String TEXT_15 = ";";
  protected final String TEXT_16 = NL + "helper ";
  protected final String TEXT_17 = ";";
  protected final String TEXT_18 = NL + "lazy rule ";
  protected final String TEXT_19 = NL + "rule ";
  protected final String TEXT_20 = " {";
  protected final String TEXT_21 = NL + "\tfrom ";
  protected final String TEXT_22 = NL + "\t\t";
  protected final String TEXT_23 = ",";
  protected final String TEXT_24 = NL + "\tusing {";
  protected final String TEXT_25 = NL + "\t\t";
  protected final String TEXT_26 = " : ";
  protected final String TEXT_27 = " = ";
  protected final String TEXT_28 = ";" + NL;
  protected final String TEXT_29 = NL + "\t}" + NL + "\tto";
  protected final String TEXT_30 = NL + "\t\t";
  protected final String TEXT_31 = ",";
  protected final String TEXT_32 = NL + "\tdo {";
  protected final String TEXT_33 = NL + "\t\t";
  protected final String TEXT_34 = ";";
  protected final String TEXT_35 = NL + "\t}" + NL + "}";
  protected final String TEXT_36 = NL + NL + NL;
  protected final String TEXT_37 = NL;

  public String generate(Object argument)
  {
    final StringBuffer stringBuffer = new StringBuffer();
    IATLModule module = (IATLModule)argument;
    
	for (IATLMetaModel metamodel : module.getMetaModels()) {

    stringBuffer.append(TEXT_1);
    stringBuffer.append(metamodel.getMetaModelName());
    stringBuffer.append(TEXT_2);
    stringBuffer.append(metamodel.getMetaMdoelAddress());
    stringBuffer.append(TEXT_3);
    	
	}
	//generate header part
	IATLHeader header = module.getHeader();

    stringBuffer.append(TEXT_4);
    stringBuffer.append(header.getName());
    stringBuffer.append(TEXT_5);
    
	if (header.isRefine()) {

    stringBuffer.append(TEXT_6);
    
	} else {

    stringBuffer.append(TEXT_7);
    
	}
	//output target model
	for (int i = 0; i < header.getTargets().size(); i++) {

    
		// if not first element, add "," before it
		if (i!=0) {

    stringBuffer.append(TEXT_8);
    
		}

    stringBuffer.append(header.getTargets().get(i).getName());
    stringBuffer.append(TEXT_9);
    stringBuffer.append(header.getTargets().get(i).getMetaModelName());
    
	}

    stringBuffer.append(TEXT_10);
    
	//output source model
	for (int i = 0; i < header.getSources().size(); i++) {

    
		// if not first element, add "," before it
		if (i!=0) {

    stringBuffer.append(TEXT_11);
    
		}

    stringBuffer.append(header.getSources().get(i).getName());
    stringBuffer.append(TEXT_12);
    stringBuffer.append(header.getSources().get(i).getMetaModelName());
    
	}

    stringBuffer.append(TEXT_13);
    
	//generate import part
	for(IATLImport ipt : module.getImports()) {

    stringBuffer.append(TEXT_14);
    stringBuffer.append(ipt.getContent());
    stringBuffer.append(TEXT_15);
    
	}
	//generate helper part
	for(IATLHelper helper : module.getHelpers()) {

    stringBuffer.append(TEXT_16);
    stringBuffer.append(helper.getContent());
    stringBuffer.append(TEXT_17);
    
	}
	//rule part
	for (IATLRule rule : module.getRules()) {
		if (rule.getType() == EATLRuleType.lazy) {

    stringBuffer.append(TEXT_18);
    stringBuffer.append(rule.getName());
    
		} else {

    stringBuffer.append(TEXT_19);
    stringBuffer.append(rule.getName());
    stringBuffer.append(TEXT_20);
    
		}

    stringBuffer.append(TEXT_21);
    
		int size = rule.getSourcePattern().getNodes().size();
		int count = 0;
		for(IATLNode node : rule.getSourcePattern().getNodes()) {
			count ++;

    stringBuffer.append(TEXT_22);
    stringBuffer.append(node.toString());
    
			if (count != size)

    stringBuffer.append(TEXT_23);
    
		}

    stringBuffer.append(TEXT_24);
    
		//generate local variable
		for(IATLVariable v : rule.getVariable()) {

    stringBuffer.append(TEXT_25);
    stringBuffer.append(v.getName());
    stringBuffer.append(TEXT_26);
    stringBuffer.append(v.getType().getName());
    stringBuffer.append(TEXT_27);
    stringBuffer.append(v.getInitValue());
    stringBuffer.append(TEXT_28);
    
		}

    stringBuffer.append(TEXT_29);
    
		//generate target pattern
		size = rule.getTargetPattern().getNodes().size();
		count = 0;
		for(IATLNode node : rule.getTargetPattern().getNodes()) {
			count++;

    stringBuffer.append(TEXT_30);
    stringBuffer.append(node.toString());
    
			if(count != size) {				

    stringBuffer.append(TEXT_31);
    
			}
		}

    stringBuffer.append(TEXT_32);
    
		//generate expressions
		for(IATLExpression exp : rule.getImperativeExps()) {

    stringBuffer.append(TEXT_33);
    stringBuffer.append(exp.getContent());
    stringBuffer.append(TEXT_34);
    
		}

    stringBuffer.append(TEXT_35);
    
	}

    stringBuffer.append(TEXT_36);
    stringBuffer.append(TEXT_37);
    return stringBuffer.toString();
  }
}
